package org.wyn.mongodb.common;

import java.net.UnknownHostException;
import java.util.ArrayList;
import java.util.List;

import org.wyn.common.Table;
import org.wyn.mongodb.bean.Keys;
import org.wyn.util.PropertieUtil;

import com.google.code.morphia.Datastore;
import com.google.code.morphia.Morphia;
import com.mongodb.DB;
import com.mongodb.Mongo;
import com.mongodb.ServerAddress;

public class ConnectionPool {

	static {
		System.setProperty("MONGO.POOLSIZE", "40");
	}
	private static String dbName = PropertieUtil.getStrProp("mongoDB", "searchDB.name");
	private static List<ServerAddress> adds = initAdds();
	private static List<Mongo> staticMongos = intiMonos();
	private static List<Mongo> mongos = staticMongos;
	private static List<Datastore> staticDs = initDatastore();
	private static List<Datastore> dss = staticDs;

	private static List<Datastore> initDatastore() {
		List<Datastore> dss = new ArrayList<Datastore>();
		Morphia mp = new Morphia();
		for(Mongo mg : mongos) {
			try {
				if(mg == null) {
					dss.add(null);
				}
				Datastore ds = mp.createDatastore(mg, dbName);
				dss.add(ds);
			} catch (Exception e) {
				dss.add(null);
			}
		}
		return dss;
	}
	
	private static List<Mongo> intiMonos() {
		List<Mongo> mgs = new ArrayList<Mongo>();
		for(ServerAddress sa : adds) {
			try {
				Mongo mg = new Mongo(sa);
				mgs.add(mg);
			} catch (Exception e) {
				mgs.add(null);
			}
		}
		return mgs;
	}
	private static List<ServerAddress> initAdds() {
		List<ServerAddress> adds = new ArrayList<ServerAddress>();
		try {
			String addrString = PropertieUtil.getStrProp("mongoDB", "searchDB.addresses");
			String[] addrs = addrString.split(",");
			for(int i = 0, len = addrs.length; i < len; i ++) {
				String addr = addrs[i];
				String host = addr.split(":")[0];
				int port = Integer.parseInt(addr.split(":")[1]);
				adds.add(new ServerAddress(host, port));
			}
		} catch (UnknownHostException e) {
			e.printStackTrace();
		}
		return adds;
	}
	
	private static List<Mongo> checkMongos() {
		List<Mongo> mgs = new ArrayList<Mongo>();
		int i = 0;
		for(Mongo mg : staticMongos) {
			try {
				if(mg.getDB(dbName).getCollection(Table.CollectionName.Keys).count() >= 0) {
					mgs.add(mg);
				}
			} catch (Exception e) {
			}
			i ++;
		}
		return mgs;
	}
	private static List<Datastore> checkDatastore() {
		List<Datastore> dtas = new ArrayList<Datastore>();
		int i = 0;
		for(Datastore ds : staticDs) {
			try {
				if(ds.createQuery(Keys.class).countAll() >= 0) {
					dtas.add(ds);
				}
			} catch (Exception e) {
			}
			i ++;
		}
		return dtas;
	}
	
	public static void checkConnection() {
		ConnectionPool.mongos = checkMongos();
		ConnectionPool.dss = checkDatastore();
	}

	public static Datastore getInstance() {
		try {
//			Random r = new Random(System.currentTimeMillis());
//			Datastore ds = null;
//			int counter = dss.size();
//			int i = r.nextInt(1000)%counter;
//			int index = 1;
//			do{
//				ds = dss.get(i);
//				i = (i + 1)%counter;
//				index ++;
//				if(ds != null) {
//					return ds;
//				}
//			}while(ds == null && index <= counter);
//			return null;
			return dss.get(0);
		} catch (Exception e) {
			return dss.get(dss.size() - 1);
		}
	}
	public static DB getDB(){
		return mongos.get(0).getDB(dbName);
	}
	
	public static void main(String[] args) throws InterruptedException {
	}
}
